﻿/*
 * This file is part of SCWS.
 * SCWS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 * 
 * Foobar is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 * along with SCWS.  If not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml;



namespace ScwsClient
{
    class Client
    {
        const int ERR_NORMAL = 0;
        const int ERR_NOARGS = 1;
        const int ERR_INVALIDARGS = 2;
        const int ERR_CAUGHTEXCEPTION = 3;

        //static bool outXml = false;
        static bool debug = false;

        /// <summary>
        /// The magic starts here
        /// This short function deals out the work to the parseArgs function
        /// after inserting a blank line (so we only have to do this once)
        /// 
        /// After all the work has been done, the retuen value is read and some
        /// text is displayed
        /// </summary>
        /// <param name="args">the command line arguments as an array of strings</param>
        /// <returns>Integer</returns>
        static int Main(string[] args)
        {
            Console.WriteLine();

            int results = -1;

            results = parseArgs(args);

            switch (results)
            {
                case ERR_NOARGS:
                    Console.WriteLine("No argumnets specified");
                    break;
                case ERR_INVALIDARGS:
                    Console.WriteLine("Invalid arguments specified");
                    break;
                case ERR_CAUGHTEXCEPTION:
                    Console.WriteLine("Exception caught");
                    break;
                default:
                    break;
            }

            return results;
        }

        /// <summary>
        /// This is where the arguments are processed (if any) and their legitimecy
        /// is ascertained.  There are a few helper functions here that enumerate
        /// through all the arguments looking for stuff.
        /// 
        /// If all is tickedy-boo then we'll call the worker functions
        /// to talk to the webservice.
        /// 
        /// This function also decides whether to enable XML or debugging output.
        /// </summary>
        /// <param name="args">those same arguments from the Main function</param>
        /// <returns>Integer</returns>
        static int parseArgs(string[] args)
        {
            if (args.Length == 0)
            {
                showHelp(null);
                return ERR_NOARGS;
            }

            //outXml = parseArgsCheckIfExists(args, "-x");

            debug = parseArgsCheckIfExists(args, "-d");

            int result = -1;

            string rms, comment, name, monitoringobjectid, reason = null;
            int minutes = 0;
            bool recursive = true;

            switch (args[0].ToLower())
            {
                case "mmreasons":
                    result = getMmReasons();
                    break;

                case "getmonitoringobject":
                    try
                    {
                        rms = parseArgsGetParam(args, "rms");
                        monitoringobjectid = parseArgsGetParam(args, "monitoringobjectid");
                    }
                    catch (Exception ex)
                    {
                        showHelp(ex.Message);
                        return ERR_INVALIDARGS;
                    }
                    result = getMonitoringObjectInfo(rms, monitoringobjectid);
                    break;

                case "inmm":
                    try
                    {
                        rms = parseArgsGetParam(args, "rms");
                    }
                    catch (Exception ex)
                    {
                        showHelp(ex.Message);
                        return ERR_INVALIDARGS;
                    }
                    result = getObjectsInMM(rms);
                    break;

                case "mmid":
                    try
                    {
                        rms = parseArgsGetParam(args, "rms");
                        monitoringobjectid = parseArgsGetParam(args, "id");
                        comment = parseArgsGetParam(args, "comment");
                        reason = parseArgsGetParam(args, "reason");
                        minutes = Convert.ToInt32(parseArgsGetParam(args, "min"));
                        recursive = Convert.ToBoolean(parseArgsGetParam(args, "recurse").ToLower());
                    }
                    catch (Exception ex)
                    {
                        showHelp(ex.Message);
                        return ERR_INVALIDARGS;
                    }
                    result = mmStartByMonitoringObjectId(rms, monitoringobjectid, minutes,
                                                            reason, comment, recursive);
                    break;

                case "mmwin":
                    try
                    {
                        rms = parseArgsGetParam(args, "rms");
                        name = parseArgsGetParam(args, "name");
                        comment = parseArgsGetParam(args, "comment");
                        reason = parseArgsGetParam(args, "reason");
                        minutes = Convert.ToInt32(parseArgsGetParam(args, "min"));
                        
                    }
                    catch (Exception ex)
                    {
                        showHelp(ex.Message);
                        return ERR_INVALIDARGS;
                    }
                    result = mmStartByWindowsComputerName(rms, name, minutes, reason, comment);
                    break;

                case "mmgrp":
                    try
                    {
                        rms = parseArgsGetParam(args, "rms");
                        name = parseArgsGetParam(args, "name");
                        comment = parseArgsGetParam(args, "comment");
                        reason = parseArgsGetParam(args, "reason");
                        minutes = Convert.ToInt32(parseArgsGetParam(args, "min"));

                    }
                    catch (Exception ex)
                    {
                        showHelp(ex.Message);
                        return ERR_INVALIDARGS;
                    }
                    result = mmStartByGroupName(rms, name, minutes, reason, comment);
                    break;
                
                case "stopmmgrp":
                    try
                    {
                        rms = parseArgsGetParam(args, "rms");
                        name = parseArgsGetParam(args, "name");
                    }
                    catch (Exception ex)
                    {
                        showHelp(ex.Message);
                        return ERR_INVALIDARGS;
                    }
                    result = mmStopByGroupName(rms, name);
                    break;

                case "stopmmwin":
                    try
                    {
                        rms = parseArgsGetParam(args, "rms");
                        name = parseArgsGetParam(args, "name");
                    }
                    catch (Exception ex)
                    {
                        showHelp(ex.Message);
                        return ERR_INVALIDARGS;
                    }
                    result = mmStopByWindowsComputerName(rms, name);
                    break;

                case "stopmmid":
                    try
                    {
                        rms = parseArgsGetParam(args, "rms");
                        monitoringobjectid = parseArgsGetParam(args, "id");
                        recursive = Convert.ToBoolean(parseArgsGetParam(args, "recurse").ToLower());
                    }
                    catch (Exception ex)
                    {
                        showHelp(ex.Message);
                        return ERR_INVALIDARGS;
                    }
                    result = mmStopByMonitoringObjectId(rms, monitoringobjectid, recursive);
                    break;

                default:
                    showHelp(null);
                    result = ERR_INVALIDARGS;
                    break;
            }

            return result;

        }


        /// <summary>
        /// This helper of parseAegs will look for a given parameter name in the arguments
        /// supplied and return the value (the next argument in the array)
        /// 
        /// If none are found then null is returned
        /// </summary>
        /// <param name="args">those arguments again</param>
        /// <param name="param">the parameter we are looking for</param>
        /// <returns>string</returns>
        static string parseArgsGetParam(string[] args, string param)
        {
            string result = null;

            for (int i = 1; i < args.Length; i++ )
            {
                if (args[i].ToLower() == "-" + param.ToLower())
                {
                    result = args[i + 1];
                    break;
                }
                
            }
            if (result == null)
                throw new ArgumentException("Error: " + param.ToUpper() + " argument is invalid");

            return result;
        }


        /// <summary>
        /// This helper os parseArgs looks for a parameter to see if it exists.
        /// </summary>
        /// <param name="args">those arguments again</param>
        /// <param name="arg">the parameter we are looking for</param>
        /// <returns></returns>
        static bool parseArgsCheckIfExists(string[] args, string arg)
        {
            foreach(string a in args)
            {
                if (a.ToLower() == arg)
                    return true;
            }
            
            return false;
        }

        /// <summary>
        /// This functions is called if an excpetion is caught.
        /// it will display the message of the exception.
        /// 
        /// If debugging is enabled, innerexceptions and stack trace are
        /// shown.
        /// 
        /// An integer is returned, this will eventually be the return value.
        /// </summary>
        /// <param name="ex">the exception</param>
        /// <returns>integer</returns>
        static int handleError(Exception ex)
        {
            Console.WriteLine(ex.Message);
            Console.WriteLine();
            if (debug)
            {
                try
                {
                    do
                    {
                        Console.WriteLine(ex.InnerException.Message);
                        ex = ex.InnerException;
                    } while (false);

                }
                catch (Exception)
                {
                }

                finally
                {
                    Console.Write(ex.StackTrace + "\n\n");
                }
            }

            return ERR_CAUGHTEXCEPTION;

        }


        /// <summary>
        /// Displays help and usage information.
        /// </summary>
        static void showHelp(string message)
        {
            
            const string help = "ScwsClient\n"
                + "\n"
                + "Usage:\n"
                + "\n"
                + "  ScwsClient.exe {Action} [-d] [-Param1 Value] [-Param2 Value]...\n"
                + "\n\n"
                + "  Where {Action} is:\n\n"
                + "  MMReasons : Gets all valid maint mode reasons.\n"
                + "    No parameters required\n"
                + "\n"
                + "  GetMonitoringObject : Displays information about a monitoring object.\n"
                + "    -Rms [rms server name]\n"
                + "    -Id [monitoring object id]\n"
                + "\n"
                + "  InMM : Gets all objects currently in maint mode.\n"
                + "    -Rms [rms server name]\n"
                + "\n"
                + "  MMId : Starts maint mode for a particular monitoring object id.\n"
                + "    -Rms [rms server name]\n"
                + "    -Id [monitoring object id]\n"
                + "    -Min [number of minutes]\n"
                + "    -Comment [comment]\n"
                + "    -Reason [maintenance mode reason]\n"
                + "    -Recurse [true/false]\n"
                + "\n"
                + "  MMWin : Searches for, then starts maint mode for a single windows computer.\n"
                + "    -Rms [rms server name]\n"
                + "    -Name [computer name to search for]\n"
                + "    -Min [number of minutes]\n"
                + "    -Comment [comment]\n"
                + "    -Reason [maintenance mode reason]\n"
                + "\n"
                + "  MMGrp : Searches for, then starts maint mode for a group of objects.\n"
                + "    -Rms [rms server name]\n"
                + "    -Name [group name to search for]\n"
                + "    -Min [number of minutes]\n"
                + "    -Comment [comment]\n"
                + "    -Reason [maintenance mode reason]\n"
                + "\n"
                + "  StopMMId : Stops maint mode for a particular monitoring object id.\n"
                + "    -Rms [rms server name]\n"
                + "    -Id [monitoring object id]\n"
                + "    -Recurse [true/false]\n"
                + "\n"
                + "  StopMMWin : Searches for, then stops maint mode for a single windows computer.\n"
                + "    -Rms [rms server name]\n"
                + "    -Name [computer name to search for]\n"
                + "\n"
                + "  StopMMGrp : Searches for, then stops maint mode for a group of objects.\n"
                + "    -Rms [rms server name]\n"
                + "    -Name [group name to search for]\n"
                + "\n"
                + "Common switches:\n"
                + "  -d Enable debuging output\n"
                + "\n\n";

            Console.Write(help);
            if(message != null)
                Console.Write(message + "\n\n");
        }


        /// <summary>
        /// Gets the webservice object and assigns the default
        /// network credentials.
        /// </summary>
        /// <returns>WebService object</returns>
        static ScwsClient.Scws.Om getWebService()
        {
            ScwsClient.Scws.Om Omws = new ScwsClient.Scws.Om();

            Omws.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;

            return Omws;
        }


        /// <summary>
        /// Displays the contents of the supplied datatable in XML
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        static int outDataTable(DataTable dt)
        {
            System.IO.StringWriter writer = new System.IO.StringWriter();
            dt.WriteXml(writer, XmlWriteMode.IgnoreSchema, true);
            Console.Write(writer.ToString());

            return ERR_NORMAL;

        }



        #region Web Service Comms


        static int getMmReasons()
        {
            try
            {
                string[] reasons = getWebService().GetMMReasons();

                foreach (string r in reasons)
                {
                    Console.WriteLine(r);
                }
                return 0;
            }
            catch (Exception ex)
            {
                return handleError(ex);
            }
        }


        static int getMonitoringObjectInfo(string rms, string monitoringobjectid)
        {
            try
            {
                DataTable dt = getWebService().GetMonitoringObjectInfo(rms, monitoringobjectid).Tables[0];
                return outDataTable(dt);
            }
            catch(Exception ex)
            {
                return handleError(ex);
            }
        }


        static int getObjectsInMM(string rms)
        {
            try
            {
                DataTable dt = getWebService().GetObjectsInMM(rms).Tables[0];
                return outDataTable(dt);
            }
            catch (Exception ex)
            {
                return handleError(ex);
            }
        }


        static int mmStartByMonitoringObjectId(string rms, string monitoringobjectid,
                                                int minutes, string reason, string comment, bool recursive)
        {
            try
            {
                DataTable dt = getWebService().MMStartByMonitoringObjectId(monitoringobjectid, rms, 
                                                minutes, reason, comment, recursive).Tables[0];

                return outDataTable(dt);
            }
            catch (Exception ex)
            {
                return handleError(ex);
            }
        }


        static int mmStartByWindowsComputerName(string rms, string windowscomputername,
                                        int minutes, string reason, string comment)
        {
            try
            {
                DataTable dt = getWebService().MMStartByWindowsComputerName(windowscomputername, rms, 
                                                                minutes, reason, comment).Tables[0];

                return outDataTable(dt);
            }
            catch (Exception ex)
            {
                return handleError(ex);
            }
        }


        static int mmStartByGroupName(string rms, string groupname,
                                        int minutes, string reason, string comment)
        {
            try
            {
                DataTable dt = getWebService().MMStartByGroupName(groupname, rms,
                                                minutes, reason, comment).Tables[0];

                return outDataTable(dt);
            }
            catch (Exception ex)
            {
                return handleError(ex);
            }
        }

        static int mmStopByMonitoringObjectId(string rms, string monitoringobjectid,
                                                bool recursive)
        {
            try
            {
                DataTable dt = getWebService().MMStopByMonitoringObjectId(monitoringobjectid, rms, recursive).Tables[0];

                return outDataTable(dt);
            }
            catch (Exception ex)
            {
                return handleError(ex);
            }

        }

        static int mmStopByWindowsComputerName(string rms, string windowscomputername)
        {
            try
            {
                DataTable dt = getWebService().MMStopByWindowsComputerName(windowscomputername, rms).Tables[0];

                return outDataTable(dt);
            }
            catch (Exception ex)
            {
                return handleError(ex);
            }

        }


        static int mmStopByGroupName(string rms, string groupname)
        {
            try
            {
                DataTable dt = getWebService().MMStopByGroupName(groupname, rms).Tables[0];

                return outDataTable(dt);
            }
            catch (Exception ex)
            {
                return handleError(ex);
            }
        }

        #endregion //Web service comms

    }
}
